package jehc.cloud.oauth.client.timer.task;
import jehc.cloud.common.base.BaseResult;
import jehc.cloud.common.util.CollectionUtil;
import jehc.cloud.common.util.RestTemplateUtil;
import jehc.cloud.common.util.SpringUtils;
import jehc.cloud.oauth.client.service.PushService;
import jehc.cloud.oauth.client.vo.Token;
import lombok.extern.slf4j.Slf4j;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.RecursiveTask;

/**
 * @Desc 多任务分解
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Slf4j
public class ExpireTokenTask extends RecursiveTask<Integer> {

    Map<String,Token> map;

    int groupNumber;

    RestTemplateUtil restTemplateUtil;

    public ExpireTokenTask(Map<String,Token> map, int groupNumber){
        this.map = map;
        this.groupNumber = groupNumber;
    }

    public ExpireTokenTask(Map<String,Token> map, int groupNumber, RestTemplateUtil restTemplateUtil){
        this.map = map;
        this.groupNumber = groupNumber;
        this.restTemplateUtil = restTemplateUtil;
    }

    @Override
    protected Integer compute() {
        int result=0;
        if(cn.hutool.core.collection.CollectionUtil.isEmpty(map)){
            return result;
        }
        if(map.size()<=groupNumber){
            //一个任务即可
            result+=doCallable(map);
        }else{
            //拆分任务
            List<ExpireTokenTask> subTaskList =createSubTasks(map);
//            //方法一 采用fork（注意：该效率不是太高）
//            for(FasErrorTask subTask :subTaskList){
//                subTask.fork();//子任务计划执行
//            }

            //方法二 采用invokeAll（注意：该效率高一些）
            invokeAll(subTaskList);

            //合并执行结果
            for(ExpireTokenTask subTask :subTaskList){
                result+=subTask.join();
            }
        }
        return result;
    }

    /**
     *
     * @param map
     * @return
     */
    private Integer doCallable(Map<String,Token> map){
        Integer result = push(map);
       return result;
    }

    /**
     * 创建子任务
     * @param map
     * @return
     */
    private List<ExpireTokenTask> createSubTasks(Map<String,Token> map) {
        List<ExpireTokenTask> subTasks = new ArrayList<ExpireTokenTask>();
        List<Map<String,Token>> dataMap = CollectionUtil.mapChunk(map,groupNumber);
        for(Map<String,Token> tokenMap:dataMap){
            ExpireTokenTask expireTokenTask = new ExpireTokenTask(tokenMap,groupNumber,restTemplateUtil);
            subTasks.add(expireTokenTask);
        }
        return subTasks;
    }
    /**
     * 推送
     */
    public Integer push(Map<String,Token> tokenMap){
        Integer result=0;
        if(cn.hutool.core.collection.CollectionUtil.isEmpty(tokenMap)){
            log.info("没有可推送的Token有效性信息...");
            return 0;
        }
        try{
            BaseResult baseResult = restTemplateUtil.post(restTemplateUtil.restOauthURL() + "/batchUpdateExpire",BaseResult.class,tokenMap);
            if(null == baseResult || !baseResult.getSuccess()){
                log.error("更新失败，Token：{}",tokenMap);
            }
            //更新本地Token
            Map<String,Token> mapToken = (Map) baseResult.getData();
            if(!cn.hutool.core.collection.CollectionUtil.isEmpty(mapToken)){
                PushService pushService = SpringUtils.getBean(PushService.class);
                Iterator<Map.Entry<String, Token>> entryIterator = mapToken.entrySet().iterator();
                while (entryIterator.hasNext()) {
                    Map.Entry<String, Token> e = entryIterator.next();
                    Token token = pushService.get(e.getKey());
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    token.setUpdateTimes(sdf.format(new Date()));
                    token.setSuccess(true);
                    token.setKeepAlive(false);
                    pushService.put(e.getKey(),token);
                    result++;
                }
            }
            log.info("更新成功，Token：{}-{}",tokenMap,result);
        }catch (Exception e){
            log.error("更新失败，Token：{}-{}-{}",tokenMap,result,e);
        }
        return result;
    }
}
